home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / UUPC3 / (UUPC__) / DCPCRON.H next >
Text File  |  1990-03-20  |  9KB  |  296 lines

  1.  
  2. typedef struct {
  3.     char min[40];
  4.     char hour[40];
  5.     char day[40];
  6.     char month[40];
  7.     char weekday[40];
  8.     char name[40];
  9.     int retrytime;    /* minutes between retries */
  10. } schedule_record;
  11.     
  12. typedef int datalist[61];
  13.  
  14. typedef struct {
  15.     datalist min;
  16.     datalist hour;
  17.     datalist day;
  18.     datalist month;
  19.     datalist weekday;
  20. } schedule_list_record;
  21.  
  22. typedef struct {
  23.     time_t time_secs;
  24.     char   name[40];
  25.     char   status[40];
  26. } status_record;
  27.  
  28. void Schedule_To_List(char *Schedule, datalist Schedule_List, int Min, int Max);
  29. void Compute_Next_Call_Time(status_record Last, schedule_record Schedule, struct tm *Next );
  30. int Time_Less_Than_Or_Equal(struct tm *Left, struct tm *Right);
  31.  
  32. int Time_Less_Than_Or_Equal(Left, Right)
  33. struct tm *Left;
  34. struct tm *Right;
  35. {
  36.     /* check the months first */
  37.     if (Left->tm_mon < Right->tm_mon) return TRUE;
  38.     if (Left->tm_mon > Right->tm_mon) return FALSE;
  39.     
  40.     /* months are the same, check the day */
  41.     if (Left->tm_mday < Right->tm_mday) return TRUE;
  42.     if (Left->tm_mday > Right->tm_mday) return FALSE;
  43.     
  44.     /* days are the same, check the hour */
  45.     if (Left->tm_hour < Right->tm_hour) return TRUE;
  46.     if (Left->tm_hour > Right->tm_hour) return FALSE;
  47.     
  48.     /* hours are the same, check the minute */
  49.     if (Left->tm_min > Right->tm_min) return FALSE;
  50.     return TRUE;
  51. }
  52.  
  53.  
  54. void Schedule_To_List(Schedule, Schedule_List, Min, Max)
  55. char *Schedule;
  56. datalist Schedule_List;
  57. int Min, Max;
  58. {
  59.     /* take a character string describing this schedule entry and
  60.        convert it to a list of times that are acceptable, see format
  61.        and examples below.
  62.        
  63.        Format (no spaces allowed in actual string):
  64.            number :== digit{digit}
  65.            range  :== number '-' number
  66.            item   :== range | number    
  67.            entry  :==  '*' | item {, item}
  68.        Example:
  69.            "*"  "1-5,8"  "1,3,5,7,9,11" "0-7,17-23"
  70.     */
  71.     int i,k,m;
  72.     char *p;
  73.     
  74.     if (strcmp(Schedule,"*")==SAME) {
  75.         for (i=0, k=Min; k<=Max; k++, i++) 
  76.             Schedule_List[i] = k;
  77.         return; 
  78.     }
  79.     
  80.     /* scan for list entries */
  81.     p = Schedule;
  82.     i = 0;
  83.     while (*p) {
  84.         if (isdigit(*p)) {
  85.             /* got a number */
  86.             sscanf(p, "%d", &k);        /* got a list entry */
  87.             Schedule_List[i++] = k;        /* put it in the list */
  88.             while (isdigit(*p)) p++;    /* skip past number */
  89.             
  90.         } else if (*p == ',') {
  91.             /* got a comma */
  92.             p++;        /* skip the comma */
  93.         } else if (*p == '-') {
  94.             /* got a dash, must be a range */
  95.             p++;        /* skip the dash */
  96.             sscanf(p, "%d", &m);        /* get the end of the range */
  97.             while (k <= m) {            /* put entries for the range in the list */
  98.                 Schedule_List[i++] = k++;
  99.             }
  100.             while (isdigit(*p)) p++;    /* skip past number */
  101.         } else {
  102.             p++;
  103.         }
  104.         Schedule_List[i] = -1;
  105.     }
  106. }    
  107.  
  108. int Next_Valid_Value(int Last, datalist Valid_List);
  109. int Next_Valid_Value(Last, Valid_List)
  110. int Last;
  111. datalist Valid_List;
  112. {
  113.     int i = 0;
  114.     
  115.     while ((Valid_List[i] <= Last) && (Valid_List[i] >= 0))
  116.         i++;
  117.         
  118.     if (Valid_List[i] < 0) {
  119.         /* didn't find one larger, use the first entry */
  120.         return Valid_List[0];
  121.     } else {
  122.         /* take the larger one we found */
  123.         return Valid_List[i];
  124.     }
  125. }
  126.  
  127. void Compute_Next_Call_Time(Last, Schedule, Next)
  128. status_record Last;
  129. schedule_record Schedule;
  130. struct tm *Next;
  131. {
  132.     schedule_list_record Valid_Lists;    
  133.     int carry;                /* start with a carry to increment to next time value */
  134.     int field = 0;
  135.     struct tm Last_Time;
  136.     
  137.     Last_Time = *localtime(&Last.time_secs);
  138.     Last_Time.tm_mon++;        /* make months 1 based */
  139.     *Next = Last_Time;
  140.     
  141.     Schedule_To_List(Schedule.min,     Valid_Lists.min,     0, 59);
  142.     Schedule_To_List(Schedule.hour,    Valid_Lists.hour,    0, 23);
  143.     Schedule_To_List(Schedule.day,     Valid_Lists.day,     1, 31);
  144.     Schedule_To_List(Schedule.month,   Valid_Lists.month,   1, 12);
  145.     Schedule_To_List(Schedule.weekday, Valid_Lists.weekday, 1, 7);
  146.  
  147.     /* find the next larger valid time for the field */
  148.     Next->tm_min = Last_Time.tm_min++;
  149.     Next->tm_min = Next_Valid_Value(Next->tm_min, Valid_Lists.min);
  150.     if (Next->tm_min < Last_Time.tm_min) {
  151.         /* field was set backwards, we must update the less significant fields to their
  152.            minimum values */
  153.         /* field was set backwards, we must carry 1 to the next more significant field */
  154.         carry = 1;
  155.     } else {
  156.         carry = 0;
  157.     }
  158.  
  159.     Next->tm_hour = Last_Time.tm_hour + carry;
  160.     Next->tm_hour = Next_Valid_Value(Next->tm_hour, Valid_Lists.hour);
  161.     if (Next->tm_hour < Last_Time.tm_hour) {
  162.         /* field was set backwards, we must update the less significant fields to their
  163.            minimum values */
  164.         Next->tm_min = Valid_Lists.min[0];
  165.         /* field was set backwards, we must carry 1 to the next more significant field */
  166.         carry = 1;
  167.     } else {
  168.         carry = 0;
  169.     }
  170.     
  171.     Next->tm_mday = Last_Time.tm_mday + carry;
  172.     Next->tm_mday = Next_Valid_Value(Next->tm_mday, Valid_Lists.day);
  173.     if (Next->tm_mday < Last_Time.tm_mday) {
  174.         /* field was set backwards, we must update the less significant fields to their
  175.            minimum values */
  176.         Next->tm_hour = Valid_Lists.hour[0];
  177.         Next->tm_min  = Valid_Lists.min[0];
  178.         /* field was set backwards, we must carry 1 to the next more significant field */
  179.         carry = 1;
  180.     } else {
  181.         carry = 0;
  182.     }
  183.     
  184.     Next->tm_mon = Last_Time.tm_mon + carry;
  185.     Next->tm_mon = Next_Valid_Value(Next->tm_mon, Valid_Lists.month);
  186.     if (Next->tm_mon < Last_Time.tm_mon) {
  187.         /* field was set backwards, we must update the less significant fields to their
  188.            minimum values */
  189.         Next->tm_mday = Valid_Lists.day[0];
  190.         Next->tm_hour = Valid_Lists.hour[0];
  191.         Next->tm_min  = Valid_Lists.min[0];
  192.         /* field was set backwards, we must carry 1 to the next more significant field */
  193.         carry = 1;
  194.     } else {
  195.         carry = 0;
  196.     }
  197.     
  198.     Next->tm_mon--;        /* make months 0 based again */
  199. }
  200.  
  201. /**/
  202. /*
  203. **
  204. ** checkcron()
  205. ** check if we should call a system at this time.
  206. **
  207. ** returns 'S' if system needs be called
  208. ** returns 'I' if system doesn't need to be called
  209. **
  210. ** "need" is based on schedule file not by what is spooled, use "any"
  211. ** if you want to send spooled data out.
  212. **
  213. ** system needs to be called if any of the following conditions are met:
  214. **
  215. ** (1) status file "ST.<system>" doesn't exist
  216. ** (2) status file indicates last call failed and the elapsed time since
  217. **     the failure exceeds the retrytime entry in the schedule file.
  218. ** (3) status file indicates last call was ok and according to the
  219. **     schedule file there should have been a call during the time when
  220. **     the last called occurred and the current time.
  221. */
  222. checkcron()
  223. {
  224.     FILE *fp;
  225.     char line[BUFSIZ];
  226.     char stfile[80];            /* constructed status file name */
  227.     int n;
  228.     time_t Cur_Time_Secs, Retry_Expiration;
  229.     
  230.     schedule_record Schedule;
  231.     status_record Last;
  232.     struct tm Next, Current_Time;
  233.     
  234.     /* got a real problem if schedule file is missing */
  235.     if ((fp=FOPEN(s_schedule, "r", 't')) == (FILE *)NULL)
  236.         return('I');        /* no schedule, so don't call anyone */
  237.  
  238.     n = 0;
  239.     while (n==0 && fgets(line, BUFSIZ, fp) != (char *)NULL){
  240.         /* line format:
  241.             min hour day month weekday system retrytime */
  242.         n = sscanf(line, "%s %s %s %s %s %s %d",
  243.                    Schedule.min, Schedule.hour, Schedule.day,
  244.                    Schedule.month, Schedule.weekday, Schedule.name,
  245.                    &Schedule.retrytime);
  246.         if (n != 7 ||
  247.             strcmp(rmtname, Schedule.name) != SAME) n = 0;
  248.     }
  249.     fclose(fp);
  250.     if (n == 0) return ('I');    /* didn't find the system in schedule, don't call it */
  251.     
  252.     /* we have the schedule now, now we need the current status */
  253.     sprintf(stfile, "%s%s", s_statfile, rmtname);
  254.     
  255.     /* if there is no status file, assume it has never been called */
  256.     if ((fp=FOPEN(stfile, "r", 't')) == (FILE *)NULL) return('S');
  257.     
  258.     n = 0;
  259.     if (fgets(line, BUFSIZ, fp) != (char *)NULL) {
  260.         /* got status line into buffer */
  261.         /* line format:
  262.                 ctime system status
  263.            ctime is epoch time in seconds from time function
  264.            status may be OK or FAILED */
  265.         n = sscanf(line, "%ld %s %s",
  266.                    &Last.time_secs, Last.name, Last.status);
  267.         if (n != 3 ||
  268.             strcmp(rmtname, Last.name) != SAME) n = 0;
  269.     }
  270.     fclose(fp);
  271.     if (n == 0) return ('S');    /* didn't get it's status line, call it */
  272.         
  273.     if (strcmp(Last.status,"OK") != SAME) {
  274.         /* last call failed, see if the retry time has expired */
  275.         Retry_Expiration = Last.time_secs + Schedule.retrytime * 60;
  276.         time(&Cur_Time_Secs);
  277.         if (Cur_Time_Secs >= Retry_Expiration)
  278.             return ('S');        /* retry time past, call system again */
  279.         else
  280.             return ('I');        /* not time yet, don't call system */
  281.     
  282.     } else {
  283.         /* last call was successful, see if it's time to call this system again */
  284.         Compute_Next_Call_Time( Last,        /* time of last successful call */
  285.                                 Schedule,    /* time schedule pattern */
  286.                                 &Next);        /* next time it should be called */
  287.         if (Time_Less_Than_Or_Equal(&Next, &Current_Time) == TRUE)
  288.             /* the Next time has past (it's less than the current time) so that means
  289.                we should call this system */
  290.             return ('S');        /* call this system */
  291.         else
  292.             return ('I');        /* not time to call yet, don't call system */
  293.     }
  294. }
  295.  
  296.